import geoLocationManager from '@ohos.geoLocationManager';
import dataPreferences from '@ohos.data.preferences';
import hilog from '@ohos.hilog';
import media from '@ohos.multimedia.media'
import emitter from '@ohos.events.emitter';

// 获取定位
export function getLocation(): Promise<Partial<geoLocationManager.Location>> {
  return new Promise((resolve) => {
    /**
     * 参数说明
     * https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V2/js-apis-geolocationmanager-0000001427745092-V2#ZH-CN_TOPIC_0000001574088789__locationrequestpriority
     * priority：优先级
     * scenario：场景
     * maxAccuracy：精度
     */
    const requestInfo = { 'priority': 0x202, 'scenario': 0x300, 'maxAccuracy': 0 };
    const locationChange = (err, location: geoLocationManager.Location) => {
      if (err) {
        resolve({})
      }
      if (location) {
        resolve(location)
      }
    };
    try {
      geoLocationManager.getCurrentLocation(requestInfo, locationChange);
    } catch (err) {
      resolve({})
    }
  })
}

// 首选项
class PreferencesUtil {
  preferencesMap: Map<string, dataPreferences.Preferences> = new Map()

  loadPreference(context, name: string): Promise<dataPreferences.Preferences> {
    // 加载首选项目
    return new Promise((resolve, reject) => {
      dataPreferences.getPreferences(context, name, (err, preferences) => {
        if (err) {
          hilog.error(0xFF00, "preference:load", "%{public}s load ERROR，ERROR_MSG：%{public}s", name, JSON.stringify(err));
          reject({});
        }
        hilog.info(0xFF00, "preference:load", "%{public}s load SUCCESS", name);
        this.preferencesMap.set(name, preferences)
        resolve(preferences);
      })
    })
  }

  // 获取
  get(name: string, key: string): Promise<dataPreferences.ValueType> {
    return new Promise((resolve, reject) => {
      if (!this.preferencesMap.has(name)) {
        hilog.error(0xFF00, "preference:get", "%{public}s 尚未初始化", name);
        reject('')
        return;
      }
      const currPreferences = this.preferencesMap.get(name)
      try {
        currPreferences.get(key, '', (err, val) => {
          if (err) {
            hilog.error(0xFF00, "preference:get", "%{public}s get %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
            reject('')
            return;
          }
          hilog.info(0xFF00, "preference:get", "%{public}s get %{public}s SUCCESS", name, key);
          resolve(val);
        })
      } catch (err) {
        hilog.error(0xFF00, "preference:get", "%{public}s get %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
        reject('')
      }
    })
  }

  // 添加
  add(name: string, key: string, value: dataPreferences.ValueType) {
    return new Promise((resolve, reject) => {
      const currPreferences = this.preferencesMap.get(name)
      try {
        currPreferences.has(key, function (err, val) {
          if (err) {
            hilog.error(0xFF00, "preference:add", "%{public}s add %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
            reject(false);
          }
          if (val) {
            hilog.error(0xFF00, "preference:add", "%{public}s add %{public}s is EXISTED", name, key);
            reject(false);
          } else {
            try {
              currPreferences.put(key, value, (err) => {
                if (err) {
                  hilog.error(0xFF00, "preference:add", "%{public}s add %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
                  reject(false)
                  return;
                }
                hilog.info(0xFF00, "preference:add", "%{public}s add %{public}s SUCCESS", name, key);
                currPreferences.flush()
                resolve(true)
              })
            } catch (err) {
              hilog.error(0xFF00, "preference:add", "%{public}s add %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
              reject(false)
            }
          }
        })
      } catch (err) {
        hilog.error(0xFF00, "preference:add", "%{public}s add %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
      }
    })
  }
  // 删除
  delete(name: string, key: string) {
    return new Promise((resolve, reject) => {
      const currPreferences = this.preferencesMap.get(name)
      try {
        currPreferences.delete(key, (err) => {
          if (err) {
            hilog.error(0xFF00, "preference:delete", "%{public}s delete %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
            reject(false)
            return;
          }
          hilog.error(0xFF00, "preference:delete", "%{public}s delete %{public}s SUCCESS", name, key);
          currPreferences.flush()
          resolve(true)
        })
      } catch (err) {
        hilog.error(0xFF00, "preference:delete", "%{public}s delete %{public}s ERROR，ERROR_MSG：%{public}s", name, key, JSON.stringify(err));
        reject(false)
      }
    })
  }
}

export const preferencesUtil = new PreferencesUtil() as PreferencesUtil

// 播放器
interface PlayItem {
  url: string
}

export interface PlayState {
  duration: number
  time: number
  isPlay: boolean
  playIndex: number
  playList: PlayItem[]
}

export class AVPlayer {
  // 播放器实例
  player: media.AVPlayer = null
  // 当前播放器是否在播放
  isPlay: boolean = false
  // 当前播放器播放资源的总时长
  duration: number = 0
  // 当前播放器播放的时长
  time: number = 0
  // surfaceID用于播放画面显示，具体的值需要通过XComponent接口获取
  surfaceId: string = ''
  // 当前播放器的播放列表
  playList: PlayItem[] = []
  // 当前播放的资源索引
  playIndex: number = 0
  static readonly MEDIA_UPDATE_STATE = 0
  playState: Partial<PlayState> = {}

  // 创建播放器
  async init(initParams: {
    surfaceId: string
    playList: { url: string }[],
    context: any
  }) {
    // 存储属性SurfaceID，用于设置播放窗口，显示画面
    this.surfaceId = initParams.surfaceId
    this.player = await media.createAVPlayer()

    // 用于进度条，监听进度条长度
    this.player.on('durationUpdate', (duration: number) => {
      hilog.info(0xFF00, "AVPlayer:durationUpdate", "current time: %{public}s", duration);
      // 获取资源总时长
      this.duration = duration
      // 更新信息到页面
      this.updateState()
    })

    // 用于进度条，监听进度条当前位置，刷新当前时间
    this.player.on('timeUpdate', (time) => {
      hilog.info(0xFF00, "AVPlayer:timeUpdate", "current time: %{public}s", time);
      // 获取当前播放时长
      this.time = time
    })

    // 监听seek生效的事件（拖动进度条到指定位置）
    this.player.on('seekDone', (seekDoneTime: number) => {
      hilog.info(0xFF00, "AVPlayer:seekDone", "current time: %{public}s", seekDoneTime);
      this.player.play()
      this.isPlay = true
    })

    // 监听资源播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    this.player.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源，触发idle状态
      this.player.reset()
    })

    this.player.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

      // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayer state initialized called.');
        // 设置显示画面，当播放的资源为纯音频时无需设置
          if (this.surfaceId) {
            this.player.surfaceId = this.surfaceId
          }
          this.player.prepare()
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          if (this.isPlay) {
            this.play()
          }
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          this.player.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  // 播放
  async play() {
    this.player.play()
    this.isPlay = true
    this.updateState()
  }

  // 视频暂停
  pause() {
    this.player.pause()
    this.isPlay = false
    this.updateState()
  }

  // 跳转到指定播放位置
  seekTime(time: number) {
    this.time = time
    this.player.seek(this.time)

    // 如果是暂停状态下跳转到指定播放位置，则开启播放
    if (!this.isPlay) {
      this.isPlay = true
      this.player.play()
    }
  }

  // 切换播放资源
  singlePlay(source?: string) {

    if (source) {
      let index = this.playList.findIndex((item: PlayItem) => item.url === source)

      if (index > -1) {
        // 当前要播放的资源在播放列表里
        this.playIndex = index
      } else {
        // 当前要播放的资源不在播放列表里
        this.playList.push({ url: source })
        this.playIndex = this.playList.length - 1
      }
    }
    this.changePlay()
  }

  async changePlay() {
    // 将播放状态置为闲置
    await this.player.reset()

    // 重置当前播放时长和资源时长
    this.time = 0
    this.duration = 0

    this.player.url = this.playList[this.playIndex].url
    this.updateState()
  }

  // 更新页面状态
  async updateState() {
    this.playState = {
      duration: this.duration,
      time: this.time,
      isPlay: this.isPlay,
      playIndex: this.playIndex,
      playList: this.playList,
    }
    const data = {
      playState: JSON.stringify(this.playState)
    }
    // 更新页面
    emitter.emit({
      eventId: AVPlayer.MEDIA_UPDATE_STATE,
    }, {
      data
    })
  }
}